/* 
 *	Copyright (C) 2009-2010 miaohua
 *	http://code.google.com/p/lrcshower/
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#include <Windows.h>
#include <MMSystem.h>
#include <vector>
#include <utility>
#include "LrcShow.h"

#pragma once

// Lrc text alignment(center, left, right)
static unsigned int Alignment []={
     DT_LEFT,
     DT_CENTER,
     DT_RIGHT
};

// Lrc file parser
class CLrcAnalyzer;

// Lcr show(just in a window not desktop) class
class CLrcWinShower
{
public:
     // Construnctor & destructor
     CLrcWinShower();
     ~CLrcWinShower();

     // Change the scoller's property
     bool ChangeBgClr(COLORREF Clr);
     bool ChangeFocusLineClr(COLORREF Clr);
     bool ChangeOtherLineClr(COLORREF Clr);
     bool ChangeAlign(int Opt);
     bool ChangeLineInterval(int Interval);
     bool ChangeFont(const TCHAR * FontName, int FontSize);
     bool ChangeFont(const LOGFONT* font);
     bool ChangeKaraokeMode(bool Mode);
     bool ChangeGradientMode(bool OnOrOff);
     bool ChangeMainLrcBuf(const CLrcAnalyzer & Analyzer);
     bool ChangeShowWnd(HWND Win);
     bool SetAutoResizeMode(bool Mode);
     bool SetTopMostMode(bool Mode);

     // Control functions
     // Start to show the lrc, the default option is to refresh the lrc show window automatically
     bool Start();
     // Reset the scroller to be the "start" state(show first line of the lrc)
     bool Reset();
     // Stop the lrc shower
     bool Stop();
     // Do scroll job
     // Now [in]: current time(in misecond unit)
     void DoOnTimeScrollJob(long long Now);

private: 
     // Helper functions
     // Adjust the lrc 3 buffers: the upper line buffer, focus line buffer, lower buffer
     // according to UpperCount, content of 3 buffers may need changed
     void AdjustLrcLineBuf(int UpperCount);
     // Calculate ellapse in one line
     // In current line's duration, calculate how to scroll the height of line
     void CalcEllapse(int RangeIdx);
     // Find the range for one media sample(which lrc line should be showed)
     int FindRange(long long Start);
     // Find the time slot in a range
     int FindTimeSlotRange(long long Start, int RangeIdx);
     // On time to paint    
     static void CALLBACK ScrollLrcTimeOut(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
     // On time to turn off the gradient show for the line before focus line	    
     static void CALLBACK GradientOffTimeOut(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
     void TurnOffGradient();
    
     // Show text to screen(with access lock)
     // It calls TextToScreen to do the real job
     bool ShowLrc();
     // Show text to screen(without access lock)
     // It calls LineToScreen to show one line in window
     bool TextToScreen();
     // Render helper function(without access lock)
     // Para WhichPart[in]:
     //      = 0: is upper part
     //      = 1: is the focus line
     //      = 2: is lower part
     void LineToScreen(tstring & Buffer, RECT Rect, COLORREF Clr, int WhichPart);

     // Initialize the gdi objects(without access lock)
     bool GdiObjInit();
     // Clean up the initialization(with access lock)
     void CleanUp();
     // Resize the lrc show window to accommodate the length of lrc(without access lock)
     bool ResizeWin();
     // Reset all parameters of shower(without access lock)
     bool ResetHelper();


     MMRESULT m_ScrollLrcTimer;              // Synchronal timer for scroll one line lrc show
     MMRESULT m_GrandChangeTimer;            // Timer for turn off the grandually changing function 
     HDC m_MemoryDC;                         // Memory dc of the display device context
     HDC m_WinDC;                            // Lrc show window's display device context
     int m_DrawHeight;                       // Lrc showing window's height
     int m_DrawWidth;                        // Lrc showing window's width
     int m_FirstLineTextOutY;                // Y aix output position of first line of lrc    
     int m_FocusLineWidth;                   // Current focus line lrc's width
     int m_MaxLenIdx;                        // Index of the maximum length line in lrc buffer
     int m_MaxLength;                        // Maximum length of all lrc lines
     int m_FocusLineLen;                     // Length of focus part for current focus line in karaoke mode
     HBITMAP m_MemBitmap;                    // Memory bitmap for the memory device context
     HBRUSH  m_BgBrush;                      // Color brush for background
     HFONT   m_LrcTextFont;                  // Font of lrc text
     LOGFONT m_TextLogFont;                  // LOGFONT of text 
     RECT m_ShowArea;                        // Lrc showing area
     COLORREF m_UnFocusClr;                  // Color of unfocus lrc text 
     COLORREF m_FocusClr;                    // Color of focus lrc text 
     COLORREF m_BgClr;                       // Color of background
     HWND m_ShowWinHandler;                  // Handler of window where the lrc is painted on
     const LrcBuf * m_LrcBuf;                // Lrc buffer of current playing song
     tstring  m_UpperLines;                  // Lrc lines buffer for above the focus line 
     tstring  m_FocusLine;                   // Focus line
     tstring  m_LowerLines;                  // Lrc lines buffer for below the focus line 
     int m_SigLineHeight;                    // Single lrc line's height
     int m_LineInterval;                     // Interval between lrc lines
     unsigned int m_UpperLineCount;          // Upper lrc lines number
     unsigned int m_LowerLineCount;          // Lower lrc lines number
     int m_Alignment;                        // Lrc's alignment(0:center; 1:left; 2:right)
     bool m_KaraokeMode;                     // Wether to show lrc in karaoke mode or not
     bool m_LineChgMode;                     // the flag for wether to show focus line to grandually change its color
     bool m_Gradient;                        // Change or not(the helper variable to indicate wether to paint the pre-focus line with gradual color)
     bool m_AutoResizeMode;                  // Wether auto resize window to accommodate lrc lines
     bool m_TopMostMode;                     // Wether set the lrc show window topmost
     long long m_Ellapse1;                   // Time ellapse for every 1 unit of single line height
     long long m_Ellapse2;                   // Time ellapse remainder for every 1 unit of single line height
     CRITICAL_SECTION m_ParaAccessLock;      // All parameters access & set lock
};
